package com.orchard.orchardfarmmanagementsystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.orchard.orchardfarmmanagementsystem.dto.MaintenanceRecordsDTO;
import com.orchard.orchardfarmmanagementsystem.dto.MaterialDTO;
import com.orchard.orchardfarmmanagementsystem.dto.SuppliesDTO;
import com.orchard.orchardfarmmanagementsystem.entity.Inventory;
import com.orchard.orchardfarmmanagementsystem.entity.MaintenanceRecords;
import com.orchard.orchardfarmmanagementsystem.entity.Materials;
import com.orchard.orchardfarmmanagementsystem.entity.TaskMaterialRelation;
import com.orchard.orchardfarmmanagementsystem.mapper.InventoryMapper;
import com.orchard.orchardfarmmanagementsystem.mapper.MaintenanceRecordsMapper;
import com.orchard.orchardfarmmanagementsystem.mapper.SuppliesMapper;
import com.orchard.orchardfarmmanagementsystem.mapper.TaskMaterialRelationMapper;
import com.orchard.orchardfarmmanagementsystem.service.SuppliesService;
import com.orchard.orchardfarmmanagementsystem.utils.Result;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SuppliesServiceImpl extends ServiceImpl<SuppliesMapper, Materials> implements SuppliesService {

    @Autowired
    private SuppliesMapper suppliesMapper;

    @Autowired
    private MaintenanceRecordsMapper maintenanceRecordsMapper;

    @Autowired
    private InventoryMapper inventoryMapper;

    @Autowired
    private TaskMaterialRelationMapper taskMaterialRelationMapper;

    //    批量获取物资列表：首先从 suppliesMapper 中批量获取所有物资。
//    提取所有 materialId：将所有物资的 ID 提取出来，以便后续批量查询使用。
//    批量获取维护记录：一次性获取所有与这些物资相关的维护记录，并根据 materialId 进行分组。这消除了在循环内部逐个查询维护记录的需求。
//    批量获取库存信息：同样地，一次性获取所有与这些物资相关的库存信息，并创建一个 materialId 到 Inventory 的映射表。
//    构建返回结果：最后，在流操作中构建每个 MaterialDTO 实例，设置其属性，并将所有 DTO 收集到最终的结果列表中。
    @Override
    public List<MaterialDTO> getAllMaterials() {
        // 批量获取物资列表
        List<Materials> materials = suppliesMapper.selectList(null);

        // 提取所有的 materialId 用于批量查询
        Set<Integer> materialIds = materials.stream().map(Materials::getId).collect(Collectors.toSet());

        // 批量获取所有相关联的维护记录，并按 materialId 分组
        List<MaintenanceRecords> allMaintenanceRecords = maintenanceRecordsMapper.selectList(
                new QueryWrapper<MaintenanceRecords>().in("material_id", materialIds)
        );
        Map<Integer, List<MaintenanceRecords>> maintenanceRecordsByMaterialId = allMaintenanceRecords.stream()
                .collect(Collectors.groupingBy(MaintenanceRecords::getMaterialId));

        // 批量获取所有相关的库存信息，并按 materialId 映射
        List<Inventory> inventories = inventoryMapper.selectList(
                new QueryWrapper<Inventory>().in("material_id", materialIds)
        );
        Map<Integer, Inventory> inventoryByMaterialId = inventories.stream()
                .collect(Collectors.toMap(Inventory::getMaterialId, inventory -> inventory));

        // 定义日期格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        // 构建返回结果
        List<MaterialDTO> supplies = materials.stream().map(material -> {
            MaterialDTO materialDTO = new MaterialDTO();
            BeanUtils.copyProperties(material, materialDTO);

            // 设置维修记录
            List<MaintenanceRecords> records = maintenanceRecordsByMaterialId.getOrDefault(material.getId(), Collections.emptyList());
            List<MaintenanceRecordsDTO> main_records = records.stream().map(record -> {
                MaintenanceRecordsDTO recordDTO = new MaintenanceRecordsDTO();
                BeanUtils.copyProperties(record, recordDTO);
                if (record.getMaintenanceDate() != null) {
                    // 格式化 maintenance_date
                }
                return recordDTO;
            }).collect(Collectors.toList());
            materialDTO.setMaintenanceRecords(main_records);

            // 设置库存信息
            Inventory inventory = inventoryByMaterialId.get(material.getId());
            if (inventory != null) {
                materialDTO.setCurrentQuantity(inventory.getCurrentQuantity());
            }

            return materialDTO;
        }).collect(Collectors.toList());

        return supplies;
    }


    @Override
    @Transactional
    public SuppliesDTO createMaterial(SuppliesDTO supplyData) {
        try {
            // 插入物资数据到 materials 表
            Materials material = new Materials();
            BeanUtils.copyProperties(supplyData, material);
            material.setCreatedAt(LocalDateTime.now());
            material.setUpdatedAt(LocalDateTime.now());

            int insertResult = suppliesMapper.insert(material);

            if (insertResult <= 0) {
                throw new RuntimeException("插入物资信息失败");
            }

            // 插入库存数据到 inventory 表
            supplyData.setCurrentQuantity(0);
            Integer currentQuantity = supplyData.getCurrentQuantity();
            Inventory inventory = new Inventory();
            inventory.setMaterialId(material.getId());
            inventory.setCurrentQuantity(currentQuantity);
            inventory.setLastUpdated(LocalDateTime.now());
            inventory.setThreshold(3);

            int insertInventoryResult = inventoryMapper.insert(inventory);

            if (insertInventoryResult <= 0) {
                throw new RuntimeException("插入库存信息失败");
            }

            // 返回新创建的物资信息
            return supplyData; // 或者根据需要返回其他结果

        } catch (Exception e) {
            // 记录异常日志
            e.printStackTrace(); // 实际应用中应使用日志框架（如 SLF4J + Logback）
            throw new RuntimeException("创建物资及库存信息失败", e);
        }
    }

    @Override
    @Transactional
    public SuppliesDTO updateMaterial(Integer id, SuppliesDTO supplyData) {
        try {
            // 检查物资是否存在
            Materials existingMaterial = suppliesMapper.selectById(id);
            if (existingMaterial == null) {
                throw new RuntimeException("物资信息不存在");
            }

            // 更新物资数据到 materials 表
            Materials material = new Materials();
            BeanUtils.copyProperties(supplyData, material);
            material.setId(id); // 确保 ID 不变
            material.setCreatedAt(existingMaterial.getCreatedAt()); // 保留原始创建时间
            material.setUpdatedAt(LocalDateTime.now()); // 设置更新时间为当前时间（UTC）

            int updateResult = suppliesMapper.updateById(material);

            if (updateResult <= 0) {
                throw new RuntimeException("更新物资信息失败");
            }

            // 更新库存数据到 inventory 表
            Inventory existingInventory = inventoryMapper.selectOne(new QueryWrapper<Inventory>().in("material_id", id));
            if (existingInventory == null) {
                throw new RuntimeException("库存信息不存在");
            }

//            这里不更新库存了
            Integer currentQuantity = supplyData.getCurrentQuantity();
            existingInventory.setCurrentQuantity(0);
            existingInventory.setLastUpdated(LocalDateTime.now()); // 设置更新时间为当前时间
//            existingInventory.setThreshold(Math.max(1, (int) Math.round(currentQuantity * 0.5)));

            int updateInventoryResult = inventoryMapper.updateById(existingInventory);

            if (updateInventoryResult <= 0) {
                throw new RuntimeException("更新库存信息失败");
            }

            // 返回更新后的物资信息
            return supplyData; // 或者根据需要返回其他结果

        } catch (Exception e) {
            // 记录异常日志
            throw new RuntimeException("更新物资及库存信息失败", e);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result deleteMaterial(Integer id) {
        try {
            // 检查物资是否存在
            Optional<Materials> materialOptional = Optional.ofNullable(suppliesMapper.selectById(id));
            if (!materialOptional.isPresent()) {
                return Result.error(50001, "物资信息不存在");
            }
            Materials material = materialOptional.get();

            // 检查物资是否与任务有关联
            List<TaskMaterialRelation> taskMaterials = taskMaterialRelationMapper.selectList(
                    new QueryWrapper<TaskMaterialRelation>().eq("material_id", id)
            );
            if (!taskMaterials.isEmpty()) {
                return Result.error(50001, "物资已关联任务，无法删除");
            }

            // 删除关联的维护记录
            int deleteMaintenanceResult = maintenanceRecordsMapper.delete(
                    new QueryWrapper<MaintenanceRecords>().eq("material_id", id)
            );
            if (deleteMaintenanceResult < 0) {
                throw new RuntimeException("删除维护记录失败");
            }

            // 删除关联的库存信息
            int deleteInventoryResult = inventoryMapper.delete(
                    new QueryWrapper<Inventory>().eq("material_id", id)
            );
            if (deleteInventoryResult < 0) {
                throw new RuntimeException("删除库存信息失败");
            }

            // 删除物资信息
            int deleteMaterialResult = suppliesMapper.deleteById(id);
            if (deleteMaterialResult <= 0) {
                throw new RuntimeException("删除物资信息失败");
            }

            return Result.success("物资信息删除成功");

        } catch (Exception e) {
            return Result.error(50001, "删除物资失败：" + e.getMessage());
        }
    }

}

//    @Override
//    public List<MaterialDTO> getAllMaterials() {
//
//        //返回数据体
//        List<MaterialDTO> supplies = new ArrayList<MaterialDTO>();
//        //物资list
//        List<Materials> materials = suppliesMapper.selectList(null);
//        for (int i = 0; i < materials.size() ; i++) {
//            MaterialDTO materialDTO = new MaterialDTO();
//            //设置维修记录的字段信息
//            Materials ma = materials.get(i);
//            // 在服务层或控制器中调用这个方法
//            List<MaintenanceRecords> maintenanceRecords = maintenanceRecordsMapper.selectList(
//                    new QueryWrapper<MaintenanceRecords>()
//                            .in("material_id", ma.getId())
//            );
//            ArrayList<MaintenanceRecordsDTO> main_records = new ArrayList<>();
//            for (int j = 0; j < maintenanceRecords.size(); j++) {
//                MaintenanceRecordsDTO recordsDTO = new MaintenanceRecordsDTO();
//                recordsDTO.setMaintenanceDate(maintenanceRecords.get(j).getMaintenanceDate());
//                recordsDTO.setPerformedBy(maintenanceRecords.get(j).getPerformedBy());
//                recordsDTO.setRemarks(maintenanceRecords.get(j).getRemarks());
//                main_records.add(recordsDTO);
//            }
//
//            //库存信息
//            Inventory inventory = inventoryMapper.selectOne(new QueryWrapper<Inventory>().in("material_id", ma.getId()));
//            materialDTO.setCurrentQuantity(inventory.getCurrentQuantity());
//
//            BeanUtils.copyProperties(materials.get(i),materialDTO);
//            materialDTO.setMaintenanceRecords(main_records);
//            supplies.add(materialDTO);
//        }
//        return supplies;
//    }
